// 预测页面主控制器
const PredictionMain = {
    charts: {},

    testData: null,
    updateInterval: null,
    isInitialized: false,

    // 初始化预测页面
    init: function() {
        // 检查预测页面是否可见
        const predictionSection = document.getElementById('prediction');
        if (!predictionSection || !predictionSection.classList.contains('active')) {
            console.log('[INFO] 预测页面不可见，跳过初始化');
            return;
        }

        if (this.isInitialized) {
            // 如果已经初始化，只调整图表尺寸
            console.log('[INFO] 预测页面已初始化，调整图表尺寸...');
            setTimeout(() => {
                this.resizeCharts();
            }, 100);
            return;
        }
        
        console.log('[INFO] 初始化预测页面...');
        
        // 绑定按钮事件
        this.bindEvents();
        
        // 绑定图表轮播事件
        this.bindChartSwapEvents();
        
        // 延迟初始化图表，确保容器有正确尺寸
        setTimeout(() => {
        // 初始化图表
        this.initCharts();
        
        // 加载测试数据
        this.loadTestData();
        

        
        this.isInitialized = true;
        console.log('[INFO] 预测页面初始化完成');
        }, 300);
    },

    // 初始化所有图表
    initCharts: function() {
        try {
            // 先修复图表容器尺寸
            this.fixChartContainerSizes();
            
            // 初始化温度图表
            this.charts.temperature = PredictionTemperatureChart.init('predictionTempChart');
            
            // 初始化光照图表
            this.charts.light = PredictionLightChart.init('predictionLightChart');
            
            // 初始化声音图表
            this.charts.sound = PredictionSoundChart.init('predictionSoundChart');
            
            // 初始化占用情况图表
            this.charts.occupancy = PredictionOccupancyChart.init('predictionOccupancyChart');
            
            // 延迟调整图表尺寸
            setTimeout(() => {
                this.resizeCharts();
            }, 200);
            
            console.log('[INFO] 预测图表初始化完成');
        } catch (error) {
            console.error('[ERROR] 图表初始化失败:', error);
        }
    },

    // 加载测试数据
    loadTestData: function() {
        console.log('[INFO] 加载测试数据...');
        
        fetch('/api/test-data')
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    this.testData = data.data;
                    this.updateChartsWithTestData();
                    console.log('[INFO] 测试数据加载成功');
                } else {
                    console.error('[ERROR] 测试数据加载失败:', data.error);
                    this.showError('测试数据加载失败: ' + data.error);
                }
            })
            .catch(error => {
                console.error('[ERROR] 获取测试数据失败:', error);
                this.showError('获取测试数据失败: ' + error.message);
            });
    },



    // 使用测试数据更新图表
    updateChartsWithTestData: function() {
        if (!this.testData) return;

        try {
            // 准备时间数据
            const timeData = this.testData.map(row => `${row.Date} ${row.Time}`);
            
            // 准备温度数据
            const tempData = {
                s1: this.testData.map((row, index) => [index, parseFloat(row.S1_Temp)]),
                s2: this.testData.map((row, index) => [index, parseFloat(row.S2_Temp)]),
                s3: this.testData.map((row, index) => [index, parseFloat(row.S3_Temp)]),
                s4: this.testData.map((row, index) => [index, parseFloat(row.S4_Temp)])
            };

            // 准备光照数据
            const lightData = {
                s1: this.testData.map((row, index) => [index, parseInt(row.S1_Light)]),
                s2: this.testData.map((row, index) => [index, parseInt(row.S2_Light)]),
                s3: this.testData.map((row, index) => [index, parseInt(row.S3_Light)]),
                s4: this.testData.map((row, index) => [index, parseInt(row.S4_Light)])
            };

            // 准备声音数据
            const soundData = {
                s1: this.testData.map((row, index) => [index, parseFloat(row.S1_Sound)]),
                s2: this.testData.map((row, index) => [index, parseFloat(row.S2_Sound)]),
                s3: this.testData.map((row, index) => [index, parseFloat(row.S3_Sound)]),
                s4: this.testData.map((row, index) => [index, parseFloat(row.S4_Sound)])
            };

            // 准备占用情况数据
            const occupancyData = {
                occupancy: this.testData.map((row, index) => [index, 0]), // 测试数据没有占用人数，设为0
                co2: this.testData.map((row, index) => [index, parseFloat(row.S5_CO2)]),
                pir: this.testData.map((row, index) => [index, parseInt(row.S6_PIR) + parseInt(row.S7_PIR)]),
                confidence: this.testData.map((row, index) => [index, Math.random() * 0.3 + 0.7]) // 模拟置信度
            };

            // 更新图表
            if (this.charts.temperature) {
                this.charts.temperature.update(timeData, tempData);
            }
            if (this.charts.light) {
                this.charts.light.update(timeData, lightData);
            }
            if (this.charts.sound) {
                this.charts.sound.update(timeData, soundData);
            }
            if (this.charts.occupancy) {
                this.charts.occupancy.update(timeData, occupancyData);
            }

            console.log('[INFO] 图表已用测试数据更新');
        } catch (error) {
            console.error('[ERROR] 更新图表失败:', error);
        }
    },











    // 更新最后预测时间
    updateLastPredictionTime: function() {
        const timeElement = document.getElementById('last-prediction-time');
        if (timeElement) {
            timeElement.textContent = `最后更新: ${new Date().toLocaleString()}`;
        }
    },

    // 绑定事件
    bindEvents: function() {
        // 立即预测按钮
        const predictButton = document.getElementById('predict-now');
        if (predictButton) {
            predictButton.addEventListener('click', (e) => {
                e.preventDefault();
                this.performPrediction();
            });
        }

        // 窗口大小调整时重新调整图表
        window.addEventListener('resize', () => {
            this.resizeCharts();
        });
    },

    // 执行预测
    performPrediction: function() {
        console.log('[INFO] 显示预测配置下拉框...');
        this.showPredictionDropdown();
    },

    // 显示预测配置下拉框
    showPredictionDropdown: function() {
        // 首先移除已存在的下拉框
        this.closePredictionDropdown();
        
        // 获取预测按钮位置
        const predictBtn = document.getElementById('predict-now');
        if (!predictBtn) {
            console.error('找不到预测按钮');
            return;
        }
        
        const dropdownHtml = `
            <div id="prediction-dropdown" class="prediction-dropdown">
                <div class="dropdown-header">
                    <h4>智能预测配置</h4>
                    <button class="close-btn" onclick="PredictionMain.closePredictionDropdown()">×</button>
                </div>
                
                <div class="dropdown-content">
                    <div class="config-section">
                        <label class="config-label">数据源</label>
                        <select id="input-file-select" class="config-select">
                            <option value="data/realtime_sensor_data.csv">实时传感器数据</option>
                            <option value="data/test_data.csv">测试数据</option>
                            <option value="data/room_occupancy.csv">历史数据</option>
                        </select>
                    </div>
                    
                    <div class="config-section">
                        <label class="config-label">预测时长</label>
                        <select id="prediction-duration-select" class="config-select">
                            <option value="48">24小时</option>
                            <option value="96" selected>48小时</option>
                            <option value="144">72小时</option>
                        </select>
                    </div>
                    
                    <div class="config-section">
                        <label class="config-label">预测模型</label>
                        <div class="model-checkboxes">
                            <label class="checkbox-item">
                                <input type="checkbox" value="rf" checked> 随机森林
                            </label>
                            <label class="checkbox-item">
                                <input type="checkbox" value="lstm"> LSTM神经网络
                            </label>
                            <label class="checkbox-item">
                                <input type="checkbox" value="xgb"> XGBoost
                            </label>
                        </div>
                    </div>
                    
                    <div class="config-actions">
                        <button onclick="PredictionMain.closePredictionDropdown()" class="btn-secondary">取消</button>
                        <button onclick="PredictionMain.startPredictionFromDropdown()" class="btn-primary">开始预测</button>
                    </div>
                </div>
            </div>
        `;
        
        // 添加到body，避免被其他元素遮挡
        document.body.insertAdjacentHTML('beforeend', dropdownHtml);
        
        // 添加样式
        this.addDropdownStyles();
        
        // 位置调整
        this.positionDropdown(predictBtn);
    },

    // 添加下拉框样式
    addDropdownStyles: function() {
        if (document.getElementById('prediction-dropdown-styles')) return;
        
        const style = document.createElement('style');
        style.id = 'prediction-dropdown-styles';
        style.textContent = `
            .prediction-dropdown {
                position: fixed;
                top: auto;
                right: 20px;
                width: 320px;
                background: white;
                border: 1px solid #e0e0e0;
                border-radius: 8px;
                box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
                z-index: 99999;
                margin-top: 8px;
                animation: dropdownSlideDown 0.2s ease-out;
            }
            
            @keyframes dropdownSlideDown {
                from {
                    opacity: 0;
                    transform: translateY(-10px);
                }
                to {
                    opacity: 1;
                    transform: translateY(0);
                }
            }
            
            .dropdown-header {
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 12px 16px;
                border-bottom: 1px solid #f0f0f0;
                background: linear-gradient(135deg, #f8f9fa, #e9ecef);
                border-radius: 8px 8px 0 0;
            }
            
            .dropdown-header h4 {
                margin: 0;
                font-size: 14px;
                color: #2e7d32;
                font-weight: 600;
            }
            
            .close-btn {
                background: none;
                border: none;
                font-size: 18px;
                color: #666;
                cursor: pointer;
                padding: 0;
                width: 24px;
                height: 24px;
                border-radius: 50%;
                display: flex;
                align-items: center;
                justify-content: center;
                transition: all 0.2s ease;
            }
            
            .close-btn:hover {
                background: #f0f0f0;
                color: #333;
            }
            
            .dropdown-content {
                padding: 16px;
            }
            
            .config-section {
                margin-bottom: 16px;
            }
            
            .config-section:last-of-type {
                margin-bottom: 20px;
            }
            
            .config-label {
                display: block;
                font-size: 12px;
                font-weight: 600;
                color: #444;
                margin-bottom: 6px;
            }
            
            .config-select {
                width: 100%;
                padding: 8px 12px;
                border: 1px solid #ddd;
                border-radius: 4px;
                font-size: 13px;
                background: white;
                transition: border-color 0.2s ease;
            }
            
            .config-select:focus {
                outline: none;
                border-color: #4CAF50;
                box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.1);
            }
            
            .model-checkboxes {
                display: flex;
                flex-direction: column;
                gap: 6px;
            }
            
            .checkbox-item {
                display: flex;
                align-items: center;
                font-size: 12px;
                cursor: pointer;
                padding: 4px 0;
                color: #555;
            }
            
            .checkbox-item input {
                margin-right: 8px;
                transform: scale(0.9);
            }
            
            .checkbox-item:hover {
                color: #2e7d32;
            }
            
            .config-actions {
                display: flex;
                gap: 8px;
                justify-content: flex-end;
                padding-top: 12px;
                border-top: 1px solid #f0f0f0;
            }
            
            .btn-secondary, .btn-primary {
                padding: 6px 16px;
                border: none;
                border-radius: 4px;
                font-size: 12px;
                cursor: pointer;
                transition: all 0.2s ease;
                font-weight: 500;
            }
            
            .btn-secondary {
                background: #f8f9fa;
                color: #666;
                border: 1px solid #e0e0e0;
            }
            
            .btn-secondary:hover {
                background: #e9ecef;
                color: #333;
            }
            
            .btn-primary {
                background: linear-gradient(135deg, #4CAF50, #45a049);
                color: white;
            }
            
            .btn-primary:hover {
                transform: translateY(-1px);
                box-shadow: 0 2px 8px rgba(76, 175, 80, 0.3);
            }
            
            /* 响应式调整 */
            @media (max-width: 768px) {
                .prediction-dropdown {
                    width: 280px;
                    right: -20px;
                }
            }
        `;
        document.head.appendChild(style);
    },

    // 调整下拉框位置
    positionDropdown: function(referenceBtn) {
        const dropdown = document.getElementById('prediction-dropdown');
        if (!dropdown || !referenceBtn) return;
        
        const btnRect = referenceBtn.getBoundingClientRect();
        const windowWidth = window.innerWidth;
        const windowHeight = window.innerHeight;
        
        // 计算位置
        let top = btnRect.bottom + 8;
        let right = windowWidth - btnRect.right;
        
        // 确保下拉框不会超出视窗
        if (top + 300 > windowHeight) {
            top = btnRect.top - 300 - 8; // 显示在按钮上方
        }
        
        // 确保右边有足够空间
        if (right < 320) {
            right = 20; // 最小距离右边界20px
        }
        
        dropdown.style.top = `${top}px`;
        dropdown.style.right = `${right}px`;
    },

    // 关闭预测配置下拉框
    closePredictionDropdown: function() {
        const dropdown = document.getElementById('prediction-dropdown');
        if (dropdown) {
            dropdown.remove();
        }
        
        // 移除样式
        const style = document.getElementById('prediction-dropdown-styles');
        if (style) {
            style.remove();
        }
    },

    // 显示进度区域
    showProgressArea: function(inputFile, numPredictions, selectedModels) {
        // 找到预测页面的合适位置插入进度区域
        const predictionContent = document.querySelector('#prediction .prediction-content');
        const occupancyTab = document.querySelector('.prediction-tab-content[data-content="occupancy"]');
        
        // 优先选择最合适的容器
        let targetContainer = null;
        if (occupancyTab) {
            // 在占用预测标签页中插入
            targetContainer = occupancyTab;
        } else if (predictionContent) {
            // 在预测内容区域顶部插入
            targetContainer = predictionContent;
        } else {
            // 在整个预测section中插入
            targetContainer = document.querySelector('#prediction');
        }
        
        if (!targetContainer) {
            console.error('找不到合适的容器来显示进度区域');
            return;
        }
        
        const progressHtml = `
            <div id="prediction-progress-area" class="progress-area">
                <div class="progress-header">
                    <div class="progress-title">
                        <h3>AI预测进行中</h3>
                        <button class="progress-close" onclick="PredictionMain.hideProgressArea()">×</button>
                    </div>
                    <div class="progress-config">
                        <span>数据源: ${this.getFileDisplayName(inputFile)}</span>
                        <span>预测时长: ${numPredictions/2}小时</span>
                        <span>模型: ${selectedModels.join(', ').toUpperCase()}</span>
                    </div>
                </div>
                
                <div class="progress-content">
                    <div class="progress-status">
                        <div class="status-left">
                            <div class="progress-stage">
                                <span id="current-stage">准备启动预测系统...</span>
                            </div>
                            <div class="progress-bar-container">
                                <div class="progress-bar">
                                    <div id="progress-fill" class="progress-fill"></div>
                                </div>
                                <div class="progress-percentage">
                                    <span id="progress-text">0%</span>
                                </div>
                            </div>
                        </div>
                        
                        <div class="status-right">
                            <div class="progress-steps">
                                <div class="step-item" id="step-init">
                                    <div class="step-icon">1</div>
                                    <span>初始化</span>
                                </div>
                                <div class="step-item" id="step-predict">
                                    <div class="step-icon">2</div>
                                    <span>AI预测</span>
                                </div>
                                <div class="step-item" id="step-save">
                                    <div class="step-icon">3</div>
                                    <span>保存结果</span>
                                </div>
                                <div class="step-item" id="step-complete">
                                    <div class="step-icon">4</div>
                                    <span>完成</span>
                                </div>
                            </div>
                        </div>
                    </div>
                    
                    <div class="progress-time">
                        <span>预计剩余时间: <span id="estimated-time">正在计算...</span></span>
                        <button onclick="PredictionMain.cancelPrediction()" class="btn-cancel" id="cancel-btn">
                            取消预测
                        </button>
                    </div>
                </div>
            </div>
        `;
        
        // 在目标容器顶部插入
        targetContainer.insertAdjacentHTML('afterbegin', progressHtml);
        
        this.addProgressAreaStyles();
        
        // 开始预测流程
        this.startPredictionProcess(inputFile, numPredictions, selectedModels);
    },

    // 隐藏进度区域
    hideProgressArea: function() {
        // 停止进度轮询
        this.stopProgressPolling();
        
        const progressArea = document.getElementById('prediction-progress-area');
        if (progressArea) {
            progressArea.remove();
        }
        
        const style = document.getElementById('progress-area-styles');
        if (style) {
            style.remove();
        }
        
        console.log('[INFO] 进度区域已关闭');
    },

    // 获取文件显示名称
    getFileDisplayName: function(filePath) {
        if (filePath.includes('realtime_sensor_data')) return '实时传感器数据';
        if (filePath.includes('test_data')) return '测试数据';
        if (filePath.includes('room_occupancy')) return '历史数据';
        return '数据文件';
    },

    // 添加进度区域样式
    addProgressAreaStyles: function() {
        if (document.getElementById('progress-area-styles')) return;
        
        const style = document.createElement('style');
        style.id = 'progress-area-styles';
        style.textContent = `
            .progress-area {
                background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
                border: 1px solid #e0e0e0;
                border-radius: 12px;
                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
                margin: 20px 0;
                animation: slideDown 0.3s ease-out;
                position: relative;
                overflow: hidden;
            }
            
            .progress-area::before {
                content: '';
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                height: 3px;
                background: linear-gradient(90deg, #4CAF50, #66BB6A, #81C784);
                animation: shimmer 2s infinite;
            }
            
            .progress-header {
                padding: 16px 20px;
                border-bottom: 1px solid #f0f0f0;
                background: rgba(255, 255, 255, 0.8);
                border-radius: 12px 12px 0 0;
                backdrop-filter: blur(10px);
            }
            
            .progress-title {
                display: flex;
                justify-content: space-between;
                align-items: center;
                margin-bottom: 8px;
            }
            
            .progress-title h3 {
                margin: 0;
                color: #2e7d32;
                font-size: 16px;
                font-weight: 600;
            }
            
            .progress-close {
                background: none;
                border: none;
                font-size: 20px;
                color: #999;
                cursor: pointer;
                padding: 0;
                width: 24px;
                height: 24px;
                display: flex;
                align-items: center;
                justify-content: center;
                border-radius: 4px;
            }
            
            .progress-close:hover {
                background: #e0e0e0;
                color: #333;
            }
            
            .progress-config {
                display: flex;
                gap: 20px;
                font-size: 12px;
                color: #666;
                flex-wrap: wrap;
            }
            
            .progress-config span {
                background: rgba(76, 175, 80, 0.1);
                padding: 4px 8px;
                border-radius: 4px;
                font-weight: 500;
            }
            
            .progress-content {
                padding: 16px 20px;
            }
            
            .progress-status {
                display: flex;
                gap: 20px;
                align-items: center;
                margin-bottom: 16px;
            }
            
            .status-left {
                flex: 1;
            }
            
            .progress-stage {
                margin-bottom: 12px;
            }
            
            .progress-stage span {
                font-size: 14px;
                color: #333;
                font-weight: 500;
            }
            
            .progress-bar-container {
                display: flex;
                align-items: center;
                gap: 12px;
            }
            
            .progress-bar {
                flex: 1;
                height: 6px;
                background: #f0f0f0;
                border-radius: 3px;
                overflow: hidden;
            }
            
            .progress-fill {
                height: 100%;
                background: linear-gradient(90deg, #4CAF50, #66BB6A);
                width: 0%;
                transition: width 0.5s ease;
                position: relative;
            }
            
            .progress-fill::after {
                content: '';
                position: absolute;
                top: 0;
                left: 0;
                bottom: 0;
                right: 0;
                background: linear-gradient(
                    90deg,
                    transparent,
                    rgba(255, 255, 255, 0.6),
                    transparent
                );
                animation: shimmer 2s infinite;
            }
            
            .progress-percentage {
                min-width: 35px;
                text-align: right;
                font-size: 12px;
                font-weight: 600;
                color: #4CAF50;
            }
            
            .status-right {
                flex-shrink: 0;
            }
            
            .progress-steps {
                display: flex;
                gap: 8px;
            }
            
            .step-item {
                display: flex;
                flex-direction: column;
                align-items: center;
                position: relative;
            }
            
            .step-icon {
                width: 24px;
                height: 24px;
                border-radius: 50%;
                background: #e0e0e0;
                color: #999;
                display: flex;
                align-items: center;
                justify-content: center;
                font-size: 10px;
                font-weight: 600;
                margin-bottom: 4px;
                transition: all 0.3s ease;
            }
            
            .step-item.active .step-icon {
                background: #4CAF50;
                color: white;
            }
            
            .step-item.completed .step-icon {
                background: #2e7d32;
                color: white;
            }
            
            .step-item span {
                font-size: 10px;
                color: #666;
                text-align: center;
                white-space: nowrap;
            }
            
            .step-item.active span {
                color: #4CAF50;
                font-weight: 600;
            }
            
            .progress-time {
                display: flex;
                justify-content: space-between;
                align-items: center;
                font-size: 12px;
                color: #666;
                padding-top: 12px;
                border-top: 1px solid #f0f0f0;
            }
            
            .btn-cancel {
                padding: 6px 16px;
                background: #f5f5f5;
                border: 1px solid #ddd;
                border-radius: 4px;
                color: #666;
                cursor: pointer;
                font-size: 12px;
                transition: all 0.2s ease;
            }
            
            .btn-cancel:hover {
                background: #e0e0e0;
                color: #333;
            }
            
            .btn-cancel:disabled {
                opacity: 0.5;
                cursor: not-allowed;
                background: #f0f0f0;
            }
            
            .progress-area.completed .progress-header::before {
                background: linear-gradient(90deg, #4CAF50, #66BB6A, #81C784);
            }
            
            .progress-area.error .progress-header::before {
                background: linear-gradient(90deg, #f44336, #e57373, #ffab91);
            }
            
            .progress-area.cancelled .progress-header::before {
                background: linear-gradient(90deg, #ff9800, #ffb74d, #ffcc02);
            }
            
            @keyframes slideDown {
                from { 
                    opacity: 0;
                    transform: translateY(-20px);
                }
                to { 
                    opacity: 1;
                    transform: translateY(0);
                }
            }
            
            @keyframes shimmer {
                0% { transform: translateX(-100%); }
                100% { transform: translateX(100%); }
            }
        `;
        document.head.appendChild(style);
    },

    // 开始预测流程
    startPredictionProcess: function(inputFile, numPredictions, selectedModels) {
        this.updateProgress(0, '初始化预测系统...', 'init');
        
        // 启动进度轮询
        this.startProgressPolling();
        
        // 立即开始执行预测
        this.executePrediction(inputFile, numPredictions, selectedModels);
    },

    // 开始进度轮询
    startProgressPolling: function() {
        this.progressPollingInterval = setInterval(() => {
            fetch('/api/predict/progress')
                .then(response => response.json())
                .then(data => {
                    if (data.active) {
                        this.updateProgress(data.progress, data.message, data.stage);
                    }
                })
                .catch(error => {
                    console.error('获取进度失败:', error);
                });
        }, 1000); // 每秒轮询一次
    },

    // 停止进度轮询
    stopProgressPolling: function() {
        if (this.progressPollingInterval) {
            clearInterval(this.progressPollingInterval);
            this.progressPollingInterval = null;
        }
    },

    // 执行实际预测
    executePrediction: function(inputFile, numPredictions, selectedModels) {
        fetch('/api/predict/complete', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                input_file: inputFile,
                num_predictions: numPredictions,
                models: selectedModels
            })
        })
        .then(response => response.json())
        .then(data => {
            // 停止进度轮询
            this.stopProgressPolling();
            
            if (data.success) {
                this.updateProgress(100, '预测完成! 点击右上角×号关闭进度显示', 'complete');
                
                // 添加完成状态的CSS类
                const progressArea = document.getElementById('prediction-progress-area');
                if (progressArea) {
                    progressArea.classList.add('completed');
                }
                
                // 显示预测结果，但保留进度区域
                this.displayPredictionResult(data.result);
                this.loadPredictionResults(data.result.output_file);
                
                // 禁用取消按钮，因为预测已完成
                const cancelBtn = document.getElementById('cancel-btn');
                if (cancelBtn) {
                    cancelBtn.disabled = true;
                    cancelBtn.textContent = '预测已完成';
                }
            } else {
                this.updateProgress(0, '预测失败: ' + data.error, 'error');
                
                // 添加错误状态的CSS类
                const progressArea = document.getElementById('prediction-progress-area');
                if (progressArea) {
                    progressArea.classList.add('error');
                }
                
                this.showError('预测失败: ' + data.error);
                
                // 禁用取消按钮，显示错误状态
                const cancelBtn = document.getElementById('cancel-btn');
                if (cancelBtn) {
                    cancelBtn.disabled = true;
                    cancelBtn.textContent = '预测失败';
                }
            }
        })
        .catch(error => {
            // 停止进度轮询
            this.stopProgressPolling();
            
            this.updateProgress(0, '预测系统调用失败: ' + error.message, 'error');
            
            // 添加错误状态的CSS类
            const progressArea = document.getElementById('prediction-progress-area');
            if (progressArea) {
                progressArea.classList.add('error');
            }
            
            this.showError('预测系统调用失败: ' + error.message);
            
            // 禁用取消按钮，显示错误状态
            const cancelBtn = document.getElementById('cancel-btn');
            if (cancelBtn) {
                cancelBtn.disabled = true;
                cancelBtn.textContent = '预测失败';
            }
        });
    },



    // 更新进度
    updateProgress: function(percentage, message, stage) {
        const progressFill = document.getElementById('progress-fill');
        const progressText = document.getElementById('progress-text');
        const currentStage = document.getElementById('current-stage');
        const estimatedTime = document.getElementById('estimated-time');
        
        if (progressFill) {
            progressFill.style.width = `${percentage}%`;
        }
        
        if (progressText) {
            progressText.textContent = `${percentage}%`;
        }
        
        if (currentStage) {
            currentStage.textContent = message;
        }
        
        if (estimatedTime && percentage > 0 && percentage < 100) {
            const remaining = Math.round((100 - percentage) * 0.05); // 假设每1%需要0.05分钟
            estimatedTime.textContent = remaining > 0 ? `约${remaining}分钟` : '即将完成';
        }
        
        // 更新步骤状态
        this.updateStepStatus(stage);
    },

    // 更新步骤状态
    updateStepStatus: function(currentStage) {
        const stages = ['init', 'predict', 'save', 'complete'];
        const currentIndex = stages.indexOf(currentStage);
        
        stages.forEach((stage, index) => {
            const stepElement = document.getElementById(`step-${stage}`);
            if (stepElement) {
                stepElement.classList.remove('active', 'completed');
                if (index < currentIndex) {
                    stepElement.classList.add('completed');
                } else if (index === currentIndex) {
                    stepElement.classList.add('active');
                }
            }
        });
    },



    // 取消预测
    cancelPrediction: function() {
        const cancelBtn = document.getElementById('cancel-btn');
        
        // 如果按钮已禁用，说明预测已完成或失败，不能取消
        if (cancelBtn && cancelBtn.disabled) {
            return;
        }
        
        if (confirm('确定要取消当前预测吗？')) {
            this.stopProgressPolling();
            this.updateProgress(0, '用户已取消预测', 'cancelled');
            
            // 添加取消状态的CSS类
            const progressArea = document.getElementById('prediction-progress-area');
            if (progressArea) {
                progressArea.classList.add('cancelled');
            }
            
            // 禁用按钮并更新文本
            if (cancelBtn) {
                cancelBtn.disabled = true;
                cancelBtn.textContent = '已取消';
            }
            
            console.log('[INFO] 用户取消了预测');
        }
    },

    // 显示预测结果
    displayPredictionResult: function(result) {
        console.log('[INFO] 预测完成:', result);
        // 这里可以添加显示预测结果的逻辑
        if (result.summary) {
            alert('预测完成!\n' + 
                  '输出文件: ' + result.output_file + '\n' +
                  '预测摘要: ' + result.summary);
        }
    },

    // 显示错误信息
    showError: function(message) {
        alert('错误: ' + message);
    },

    // 从下拉框开始预测
    startPredictionFromDropdown: function() {
        // 获取配置参数
        const inputFile = document.getElementById('input-file-select').value;
        const numPredictions = parseInt(document.getElementById('prediction-duration-select').value);
        
        // 获取选择的模型
        const selectedModels = [];
        const modelCheckboxes = document.querySelectorAll('.checkbox-item input:checked');
        modelCheckboxes.forEach(checkbox => {
            selectedModels.push(checkbox.value);
        });
        
        if (selectedModels.length === 0) {
            alert('请至少选择一个预测模型');
            return;
        }
        
        // 关闭下拉框
        this.closePredictionDropdown();
        
        // 开始预测
        console.log('[INFO] 开始执行预测...');
        console.log('[INFO] 配置参数:', { inputFile, numPredictions, selectedModels });
        
        // 显示进度区域
        this.showProgressArea(inputFile, numPredictions, selectedModels);
    },

    // 显示预测结果
    displayPredictionResult: function(result) {
        // 可以在页面上显示预测结果
        const resultElement = document.getElementById('prediction-result');
        if (resultElement) {
            resultElement.innerHTML = `
                <h4>预测系统完成</h4>
                <p>预测时长: <strong>${result.prediction_hours}小时</strong> (${result.num_predictions}个时间点)</p>
                <p>使用模型: <strong>${result.models_used.join(', ')}</strong></p>
                <p>输出文件: ${result.output_file}</p>
                <small>处理时间: ${result.processing_time}秒</small>
            `;
        }
        
        this.updateLastPredictionTime();
    },

    // 修复图表容器尺寸
    fixChartContainerSizes: function() {
        const chartIds = ['predictionTempChart', 'predictionLightChart', 'predictionSoundChart', 'predictionOccupancyChart'];
        
        chartIds.forEach(id => {
            const container = document.getElementById(id);
            if (container) {
                // 强制显示容器
                container.style.display = 'block';
                container.style.visibility = 'visible';
                
                // 检查容器尺寸
                const rect = container.getBoundingClientRect();
                if (rect.width === 0 || rect.height === 0) {
                    // 强制设置最小尺寸
                    container.style.minWidth = '100%';
                    if (id === 'predictionOccupancyChart') {
                        container.style.minHeight = '380px';
                    } else {
                        container.style.minHeight = '280px';
                    }
                    // 强制重新计算布局
                    container.offsetHeight;
                }
                
                console.log(`[INFO] 修复图表容器 ${id} 尺寸: ${container.offsetWidth}x${container.offsetHeight}`);
            }
        });
    },

    // 调整图表大小
    resizeCharts: function() {
        Object.values(this.charts).forEach(chart => {
            if (chart && chart.resize) {
                chart.resize();
            }
        });
    },

    // 显示错误信息
    showError: function(message) {
        const errorElement = document.getElementById('prediction-error-message');
        if (errorElement) {
            errorElement.textContent = message;
            errorElement.style.display = 'block';
            setTimeout(() => {
                errorElement.style.display = 'none';
            }, 5000);
        }
    },

    // 显示/隐藏加载状态
    showLoading: function(show) {
        const loadingElement = document.getElementById('prediction-loading-message');
        if (loadingElement) {
            loadingElement.style.display = show ? 'block' : 'none';
        }
    },

    // 销毁预测页面
    destroy: function() {
        
        // 销毁图表
        Object.values(this.charts).forEach(chart => {
            if (chart && chart.dispose) {
                chart.dispose();
            }
        });
        
        this.charts = {};
        this.isInitialized = false;
        console.log('[INFO] 预测页面已销毁');
    },

    // 加载预测结果并更新图表
    loadPredictionResults: function(prediction_file) {
        console.log('[INFO] 加载预测结果文件:', prediction_file);
        
        fetch('/api/prediction-results', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                file_path: prediction_file
            })
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                console.log('[INFO] 预测结果数据加载成功，记录数:', data.data.length);
                this.updateChartsWithPredictionData(data.data);
            } else {
                console.error('[ERROR] 预测结果加载失败:', data.error);
                this.showError('预测结果加载失败: ' + data.error);
            }
        })
        .catch(error => {
            console.error('[ERROR] 获取预测结果失败:', error);
            this.showError('获取预测结果失败: ' + error.message);
        });
    },

    // 使用预测数据更新图表
    updateChartsWithPredictionData: function(predictionData) {
        if (!predictionData || predictionData.length === 0) return;

        try {
            // 准备时间数据
            const timeData = predictionData.map(row => `${row.Date} ${row.Time}`);
            
            // 准备温度数据
            const tempData = {
                s1: predictionData.map((row, index) => [index, parseFloat(row.S1_Temp)]),
                s2: predictionData.map((row, index) => [index, parseFloat(row.S2_Temp)]),
                s3: predictionData.map((row, index) => [index, parseFloat(row.S3_Temp)]),
                s4: predictionData.map((row, index) => [index, parseFloat(row.S4_Temp)])
            };

            // 准备光照数据
            const lightData = {
                s1: predictionData.map((row, index) => [index, parseInt(row.S1_Light)]),
                s2: predictionData.map((row, index) => [index, parseInt(row.S2_Light)]),
                s3: predictionData.map((row, index) => [index, parseInt(row.S3_Light)]),
                s4: predictionData.map((row, index) => [index, parseInt(row.S4_Light)])
            };

            // 准备声音数据
            const soundData = {
                s1: predictionData.map((row, index) => [index, parseFloat(row.S1_Sound)]),
                s2: predictionData.map((row, index) => [index, parseFloat(row.S2_Sound)]),
                s3: predictionData.map((row, index) => [index, parseFloat(row.S3_Sound)]),
                s4: predictionData.map((row, index) => [index, parseFloat(row.S4_Sound)])
            };

            // 准备占用情况数据（使用预测的房间占用数据）
            const occupancyData = {
                occupancy: predictionData.map((row, index) => [index, parseInt(row.rf_prediction || row.ensemble_prediction || 0)]),
                co2: predictionData.map((row, index) => [index, parseFloat(row.S5_CO2)]),
                pir: predictionData.map((row, index) => [index, parseInt(row.S6_PIR) + parseInt(row.S7_PIR)]),
                confidence: predictionData.map((row, index) => [index, 0.9]) // 预测置信度
            };

            // 更新图表
            if (this.charts.temperature) {
                this.charts.temperature.update(timeData, tempData);
            }
            if (this.charts.light) {
                this.charts.light.update(timeData, lightData);
            }
            if (this.charts.sound) {
                this.charts.sound.update(timeData, soundData);
            }
            if (this.charts.occupancy) {
                this.charts.occupancy.update(timeData, occupancyData);
            }

            console.log('[INFO] 图表已更新为预测数据');
        } catch (error) {
            console.error('[ERROR] 更新预测图表失败:', error);
        }
    },

    // 绑定图表轮播事件
    bindChartSwapEvents: function() {
        // 监听图表轮播完成事件
        document.addEventListener('chartSwapComplete', (event) => {
            this.handleChartSwap(event.detail);
        });
        
        console.log('[INFO] 图表轮播事件已绑定');
    },

    // 处理图表交换
    handleChartSwap: function(swapDetail) {
        console.log('[INFO] 处理图表交换:', swapDetail);
        
        const { swapMode, targetKey, newMapping, containers } = swapDetail;
        
        if (swapMode) {
            // 交换模式：只重建被交换的两个图表
            this.handleDirectSwap(targetKey, newMapping);
        } else {
            // 兼容旧的轮播模式
            this.handleFullRotation(newMapping);
        }
    },

    // 处理直接交换
    handleDirectSwap: function(targetKey, newMapping) {
        try {
            // 根据targetKey确定容器ID
            const containerMapping = {
                'small1': 'predictionLightChart',
                'small2': 'predictionSoundChart'
            };
            
            const mainContainerId = 'predictionTempChart';
            const targetContainerId = containerMapping[targetKey];
            
            if (!targetContainerId) {
                console.error('[ERROR] 未知的目标键:', targetKey);
                return;
            }
            
            // 重新创建被交换的图表
            setTimeout(() => {
                // 在主位置创建新图表
                if (newMapping.main === 'temperature') {
                    this.charts.temperature = PredictionTemperatureChart.init(mainContainerId);
                } else if (newMapping.main === 'light') {
                    this.charts.light = PredictionLightChart.init(mainContainerId);
                } else if (newMapping.main === 'sound') {
                    this.charts.sound = PredictionSoundChart.init(mainContainerId);
                }
                
                // 在目标位置创建新图表
                if (newMapping[targetKey] === 'temperature') {
                    this.charts.temperature = PredictionTemperatureChart.init(targetContainerId);
                } else if (newMapping[targetKey] === 'light') {
                    this.charts.light = PredictionLightChart.init(targetContainerId);
                } else if (newMapping[targetKey] === 'sound') {
                    this.charts.sound = PredictionSoundChart.init(targetContainerId);
                }
                
                // 重新应用数据
                if (this.testData) {
                    this.updateChartsWithTestData();
                }
                
                console.log('[INFO] 图表直接交换完成, 新映射:', newMapping);
            }, 150);
            
        } catch (error) {
            console.error('[ERROR] 图表直接交换失败:', error);
        }
    },

    // 处理完整轮播（保留兼容性）
    handleFullRotation: function(newMapping) {
        try {
            // 清除旧图表实例
            Object.values(this.charts).forEach(chart => {
                if (chart && chart.dispose) {
                    chart.dispose();
                }
            });
            
            // 清空图表对象
            this.charts = {};
            
            // 重新初始化图表实例
            setTimeout(() => {
                // 根据新映射创建图表
                const createdCharts = new Set();
                
                // 主图表位置
                if (newMapping.main === 'temperature' && !createdCharts.has('temperature')) {
                    this.charts.temperature = PredictionTemperatureChart.init('predictionTempChart');
                    createdCharts.add('temperature');
                } else if (newMapping.main === 'light' && !createdCharts.has('light')) {
                    this.charts.light = PredictionLightChart.init('predictionTempChart');
                    createdCharts.add('light');
                } else if (newMapping.main === 'sound' && !createdCharts.has('sound')) {
                    this.charts.sound = PredictionSoundChart.init('predictionTempChart');
                    createdCharts.add('sound');
                }
                
                // 第一个小图表位置
                if (newMapping.small1 === 'temperature' && !createdCharts.has('temperature')) {
                    this.charts.temperature = PredictionTemperatureChart.init('predictionLightChart');
                    createdCharts.add('temperature');
                } else if (newMapping.small1 === 'light' && !createdCharts.has('light')) {
                    this.charts.light = PredictionLightChart.init('predictionLightChart');
                    createdCharts.add('light');
                } else if (newMapping.small1 === 'sound' && !createdCharts.has('sound')) {
                    this.charts.sound = PredictionSoundChart.init('predictionLightChart');
                    createdCharts.add('sound');
                }
                
                // 第二个小图表位置
                if (newMapping.small2 === 'temperature' && !createdCharts.has('temperature')) {
                    this.charts.temperature = PredictionTemperatureChart.init('predictionSoundChart');
                    createdCharts.add('temperature');
                } else if (newMapping.small2 === 'light' && !createdCharts.has('light')) {
                    this.charts.light = PredictionLightChart.init('predictionSoundChart');
                    createdCharts.add('light');
                } else if (newMapping.small2 === 'sound' && !createdCharts.has('sound')) {
                    this.charts.sound = PredictionSoundChart.init('predictionSoundChart');
                    createdCharts.add('sound');
                }
                
                // 重新创建占用情况图表（底部固定位置）
                this.charts.occupancy = PredictionOccupancyChart.init('predictionOccupancyChart');
                
                // 重新应用数据
                if (this.testData) {
                    this.updateChartsWithTestData();
                }
                
                console.log('[INFO] 图表完整轮播重建完成, 新映射:', newMapping);
            }, 150);
            
        } catch (error) {
            console.error('[ERROR] 图表完整轮播处理失败:', error);
        }
    }
};

// 导出到全局
window.PredictionMain = PredictionMain; 


